/*************************************************************************************
 * Nombre del archivo: Main.java
 * Universidad del Valle de Guatemala
 * Curso: Diseño de Lenguajes de Programación
 * @author martin
 *          Martín Guzmán 08041
 * Fecha: Febrero de 2010
 * Descripción:
*************************************************************************************/

import java.io.File;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
import java.util.LinkedList;

public class Main {

    private static Scanner scan = new Scanner(System.in);
    private static Arbol_Binario arbol_sintactico = new Arbol_Binario();
    public static char epsilon = 'e';
    public static char concat = '.';

    private static int hacer;
    private static int opciones_del_menu = 0;

    private static AFD afd1;//el construido directamente
    private static AFD afd2;//el construido del AFN
    private static AFN afn1;//usando algoritmo de thompson

    public static String path_to_save="/home/martin/Desktop/AF/regex_";
    public static int contador_automatas_creados=1;

    public static boolean imprimir_automatas_en_pantalla=true;
    public static boolean imprimir_debugueo_minimizacion=true;
    public static String regex="";


    //método main donde empieza la ejecución del programa
    public static void main(String args[])
    {
        System.out.println("\n****************************************************************************************************************");
        System.out.println(" ____                            _           ____                      _ _           _                    \n"+
                     "|  _ \\ _ __ ___  _   _  ___  ___| |_ ___    / ___|___  _ __ ___  _ __ (_) | __ _  __| | ___  _ __ ___ ___ \n"+
                     "| |_) | '__/ _ \\| | | |/ _ \\/ __| __/ _ \\  | |   / _ \\| '_ ` _ \\| '_ \\| | |/ _` |/ _` |/ _ \\| '__/ _ \\ __|\n"+
                     "|  __/| | | (_) | |_| |  __/ (__| |_ (_) | | |___ (_) | | | | | | |_) | | | (_| | (_| | (_) | | |  __\\__ \\\n"+
                     "|_|   |_|  \\___/ \\__, |\\___|\\___|\\__\\___/   \\____\\___/|_| |_| |_| .__/|_|_|\\__,_|\\__,_|\\___/|_|  \\___|___/\n"+
                     "                 |___/                                          |_|                                       ");
        System.out.println("****************************************************************************************************************");

        //ciclo para repetir hasta que quiera salir del programa
        
        do
        {
            Menu();
        } while (hacer!=opciones_del_menu);//hasta que precione salir
        System.out.println("\n¡Gracias por utilizar el programa!");
    }

    //método que despliega el menú para realizar la acción del usuario ****************************
    public static void Menu(){
        do //ciclo hasta que ingrese bien una acción a realizar
        {

            opciones_del_menu=0;

            System.out.println("\n\t******** Menu Principal ********\n");
            System.out.println((++opciones_del_menu)+"- Ingresar expresión regular (r)");
            System.out.println((++opciones_del_menu)+"- Ingresar/evaluar cadena (w)");
            System.out.println((++opciones_del_menu)+"- Salir del Programa");
            System.out.print("\t >> ¿Qué desea hacer?\tMarque el número: ");
            //despliega mensaje de error si no escoje una opcion del menu principal
            try{
                hacer=scan.nextInt();
            }
            catch(Exception exp){ //para prevenir el ingreso de algún caracter diferente a número
                System.out.println("¡Error accion no válida!\n");
                hacer=-1;
            }
            scan.nextLine();
            if ((hacer<1 || hacer>opciones_del_menu) &&(hacer!=-1))
                System.out.println("¡Error accion fuera de las opciones!\n");

        } while (hacer<1 || hacer>opciones_del_menu);
        System.out.println("\n*************************************************************\n");

        //para realizar la accion marcada arriba
        switch (hacer)
        {
            case 1://  ********* 1- Ingresar expresión regular ******************************************

                System.out.print("\tIngrese la expresión regular (r): ");
                String expresion_infix = scan.nextLine();
                Main.regex=expresion_infix;

                //reiniciar el contador de nodos...
                Nodo.contador_nodos=1;
                
                boolean error=false;

                try{
                    if(!error)
                        arbol_sintactico.Generar_arbol(expresion_infix);
                }
                catch(Exception exp){
                    System.out.println("Error al generar el árbol");
                    error=true;
                }

                if(!error){
                    try{
                        //GENERAR EL AFD DIRECTAMENTE
                        afd1= new AFD(arbol_sintactico);
                    }catch(Exception exp){
                        System.out.println("Error al generar el AFD directamente");
                        afd1=null;
                        error=true;
                    }
                }

                if(!error){
                    try{
                        //GENERAR EL AFN CON THOMPSON
                        afn1 = new AFN(arbol_sintactico);
                    }catch(Exception exp){
                        System.out.println("Error al generar el AFN con Thompson");
                        afn1=null;
                        error=true;
                    }
                }

                if(!error){
                    try{
                        //CONVERTIR EL AFN A UN AFD CON SUBCONJUNTOS
                        afd2 = new AFD(afn1);

                        contador_automatas_creados++;
                    }catch(Exception exp){
                        System.out.println("Error al generar el AFD con subconjuntos");
                        afd2=null;
                        error=true;
                    }
                }

                break;
            case 2://  ********* 2- Ingresar cadena *****************************************************
                System.out.print("\tIngrese cadena a evaluar (w): ");
                String w = scan.nextLine();

                if(w.isEmpty()){
                    w = ""+Main.epsilon;
                }

                if(afd1!=null){
                    System.out.println("\n***************************** AFD DIRECTO *****************************");

                    //EVALUAR EL AFD DIRECTO
                    afd1.Simulacion_AFD(w);
                    System.out.println("***********************************************************************");
                }

                if(afn1!=null){
                    System.out.println("\n***************************** AFN CON THOMPSON *****************************");
                    //EVALUAR EL AFN CON THOMPSON
                    afn1.Simulacion_AFN(w);
                    System.out.println("***********************************************************************");
                }

                if(afd2!=null){
                    System.out.println("\n***************************** AFD SUBCONJUNTOS *****************************");
                    //EVALUAR EL AFD CON SUBCONJUNTOS
                    afd2.Simulacion_AFD(w);
                    System.out.println("***********************************************************************");
                }

                break;
        }
    }

}
